package com.wg.net.session;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.wg.net.DisconnectReason;
import com.wg.net.SendResult;
import com.wg.net.NettyAttributeKey;
import io.netty.channel.Channel;
import io.netty.util.Attribute;

import java.net.InetSocketAddress;
import java.util.concurrent.atomic.AtomicReference;

/**
 * TCP会话实现类（基于Netty Channel）
 * <p>
 * 职责：
 * - 封装Netty Channel的生命周期管理
 * - 实现消息发送、连接断开等业务逻辑
 * - 提供本地/远程地址信息查询
 *
 * @author 少爷123
 */
public class TcpSession extends AbstractSession {
    private static final Log log = LogFactory.get();

    /**
     * Netty Channel（线程安全，由Netty管理生命周期）
     */
    protected final Channel channel;

    /**
     * 自定义数据（线程安全，使用AtomicReference）
     */
    private final AtomicReference<Object> userData = new AtomicReference<>();

    /**
     * 构造TCP会话（绑定Netty Channel）
     *
     * @param channel Netty Channel对象（不可为null）
     */
    public TcpSession(Channel channel) {
        this.channel = channel;
    }

    @Override
    public String getPeerId() {
        return channel.id().asLongText();
    }

    @Override
    public SendResult send(byte[] data) {
        if (!channel.isActive()) {
            log.warn("消息发送失败：Channel未激活 | Channel={}", channel);
            return SendResult.Disconnected;
        }
        if (!channel.isWritable()) {
            log.warn("消息发送失败：Channel不可写（缓冲区已满） | Channel={}", channel);
            return SendResult.SendBufferFull;
        }

        try {
            writeAndFlush(data);
            return SendResult.Ok;
        } catch (Exception e) {
            log.error("消息发送异常 | Channel={}", channel, e);
            return SendResult.Failed;
        }
    }

    @Override
    public void flush() {
        channel.flush();
    }

    @Override
    public void close() {
        disconnect(DisconnectReason.ManagedDisconnect);
    }

    @Override
    public void disconnect(DisconnectReason reason) {
        Attribute<DisconnectReason> attr = channel.attr(NettyAttributeKey.DISCONNECT_REASON);
        if (attr.get() == null) {
            attr.set(reason);
        }
        channel.close();
    }

    @Override
    public int getLocalPort() {
        InetSocketAddress localAddr = (InetSocketAddress) channel.localAddress();
        return localAddr != null ? localAddr.getPort() : 0;
    }

    @Override
    public String getLocalIp() {
        InetSocketAddress localAddr = (InetSocketAddress) channel.localAddress();
        return localAddr != null ? localAddr.getAddress().getHostAddress() : "0.0.0.0";
    }

    @Override
    public int getRemotePort() {
        InetSocketAddress remoteAddr = (InetSocketAddress) channel.remoteAddress();
        return remoteAddr != null ? remoteAddr.getPort() : 0;
    }

    @Override
    public String getRemoteIp() {
        InetSocketAddress remoteAddr = (InetSocketAddress) channel.remoteAddress();
        return remoteAddr != null ? remoteAddr.getAddress().getHostAddress() : "0.0.0.0";
    }

    @Override
    public Object getUserData() {
        return userData.get();
    }

    @Override
    public void setUserData(Object data) {
        userData.set(data);
    }

    /**
     * 内部方法：通过Channel写并刷新数据（异步非阻塞）
     *
     * @param data 待发送的字节数据
     */
    protected void writeAndFlush(byte[] data) {
        channel.writeAndFlush(data, channel.voidPromise());
    }
}